﻿/*****************************************************************
 * Copyright (C) Newegg Corporation. All rights reserved.
 * 
 * Author       :  Bill Li (Bill.S.Li@newegg.com)
 * Create Date  :  
 * Usage        :  
 *
 * RevisionHistory
 * Date         Author               Description
 * 
*****************************************************************/
using System;
using System.Text.RegularExpressions;
using System.Xml;
using Framework.Utils;
using System.Collections.Generic;
using Framework;

namespace TemplateEngine
{
    internal static class NodeTranslateUtil
    {
        public const string TAG_PREFIX = "<tag:";

        // 获取函数式
        private static Regex s_funReg = new Regex("[a-zA-Z]+\\([^<>()]*\\)", RegexOptions.Compiled);

        /// <summary>
        /// 执行判断式
        /// </summary>
        /// <param name="input">判断式</param>
        /// <param name="node">节点对象</param>
        /// <returns>是否正确</returns>
        public static bool ExecuteIf(string input, XmlNode node, TemplateNode templateNode)
        {
            input = input.Trim();

            // 检查是否存在需要执行的函数，如果需要执行，先执行函数，用以替换判断式中的值
            while (s_funReg.IsMatch(input))
            {
                var match = s_funReg.Match(input);
                object result = FunctionHelper.ExecuteFunction(match.Value, node, templateNode);
                input = input.Replace(match.Value, result.ToString());
            }

            // 处理节点值的替换
            int startIdx, endIdx;
            while ((startIdx = input.IndexOf("{")) != -1 && (endIdx = input.IndexOf("}")) != -1)
            {
                string xpathStr = input.Substring(startIdx, (endIdx + 1) - startIdx);

                // 剔除两边的花括号
                string xpath = xpathStr.Substring(1, xpathStr.Length - 2);
                var hitNode = node.SelectSingleNode(xpath);
                string value;
                if (hitNode == null)
                {
                    value = string.Empty;
                }
                else
                {
                    value = hitNode.InnerText;
                }

                input = input.Replace(xpathStr, value);
            }

            // 执行JS判断式子
            // 处理判断符号
            input = input.Replace("&gt;", ">");
            input = input.Replace("&lt;", "<");
            input = input.Replace("==", "===");
            input = input.Replace("!=", "!==");
            string error;
            object flg = JScriptEngine.Execute(input, out error);
            if (!string.IsNullOrEmpty(error))
            {
                throw new TemplateEngineException(error);
            }

            return Convert.ToBoolean(flg);
        }

        /// <summary>
        /// 执行判断式
        /// </summary>
        /// <param name="input">xpath</param>
        /// <param name="node">节点对象</param>
        /// <returns>是否正确</returns>
        public static string ValueOf(string input, XmlNode node)
        {
            if (string.IsNullOrEmpty(input))
            {
                throw new ArgumentNullException("input");
            }

            string attrName = null;
            int charIdx = input.LastIndexOf("@");
            if (charIdx != -1)
            {
                int tempIdx = input.LastIndexOf("]");
                if (charIdx > tempIdx)
                {
                    attrName = input.Substring(charIdx + 1, input.Length - charIdx - 1);
                }
            }

            XmlNode hitNode = node.SelectSingleNode(input);
            if (hitNode == null)
            {
                return string.Empty;
            }

            if (string.IsNullOrWhiteSpace(attrName))
            {
                return hitNode.InnerText;
            }

            var attribute = hitNode.Attributes[attrName];
            return attribute == null ? string.Empty : attribute.Value;
        }

        /// <summary>
        /// 从模板中剔出所有半节点
        /// </summary>
        /// <param name="templateStr"></param>
        /// <returns></returns>
        internal static List<TranslateHalfNode> FindAllHalfNode(string templateStr)
        {

            const string tagEnd = "</tag:";
            int currentIdx = 0,
                startIdx = 0,
                endIdx = 0,
                tempIdx;
            string nodeStr;
            List<TranslateHalfNode> result = new List<TranslateHalfNode>();
            if (string.IsNullOrWhiteSpace(templateStr))
            {
                return result;
            }

            while (templateStr.IndexOf(TAG_PREFIX, currentIdx) != -1 || templateStr.IndexOf(tagEnd, currentIdx) != -1)
            {
                startIdx = templateStr.IndexOf(TAG_PREFIX, currentIdx);
                endIdx = templateStr.IndexOf(tagEnd, currentIdx);

                if (startIdx == -1)
                {
                    startIdx = int.MaxValue;
                }
                else if (endIdx == -1)
                {
                    endIdx = int.MaxValue;
                }

                if (startIdx > endIdx)
                {
                    currentIdx = endIdx;
                }
                else
                {
                    currentIdx = startIdx;
                }

                tempIdx = templateStr.IndexOf(">", currentIdx);
                tempIdx++;
                nodeStr = templateStr.Substring(currentIdx, tempIdx - currentIdx);
                TranslateHalfNode halfNode = new TranslateHalfNode(nodeStr, currentIdx);
                currentIdx += tempIdx - currentIdx;
                result.Add(halfNode);
            }

            return result;
        }
    }
}
